package com.springcloudalibaba.baseredis.service;

import org.redisson.api.GeoEntry;
import org.redisson.api.GeoPosition;
import org.redisson.api.RBinaryStream;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @描述: Redis官方推荐的Java版的Redis客户端，功能非常强大
 * @作者: lixing
 * @日期 2021/7/1 17:18
 */
public interface RedissonSingleService<E> {
    /**
     * @描述 当前key是否存在
     * @作者 lixing
     * @日期 2021/7/4 13:58
     * @Param [key] 
     * @return boolean
     */
    boolean isExists(String key);

    /**
     * @描述 设置key指定毫秒后过期
     * @作者 lixing
     * @日期 2021/7/4 14:00
     * @Param [key, milliseconds 有效期]
     */
    void setExpire(String key, long milliseconds);

    // TODO ============================================================================================== key值自增、自减
    /**
     * @描述 设置key的值自增value后并返回
     * @作者 lixing
     * @日期 2021/7/4 14:02
     * @Param [key value]
     * @return long
     */
    long setIncrementByAtomicLong(String key, long value);
    double setIncrementAtomicDouble(String key, double value);

    /**
     * @描述 设置key的值自增
     * @作者 lixing
     * @日期 2021/7/4 14:02
     * @Param [key]
     */
    void setIncrementByLongAdder(String key);
    void setIncrementByDoubleAdder(String key);

    /**
     * @描述 设置key的值自减
     * @作者 lixing
     * @日期 2021/7/4 14:02
     * @Param [key]
     */
    void setDecrementByLongAdder(String key);
    void setDecrementByDoubleAdder(String key);
    
    // TODO ========================================================================================== 通用对象桶（Bucket）
    // TODO RBucket Java对象是一种通用对象桶可以用来存放任类型的对象
    /**
     * @描述 添加 key
     * @作者 lixing
     * @日期 2021/7/4 14:11
     * @Param [key, value]
     */
    void setKey(String key, E value);

    /**
     * @描述 添加 key
     * @作者 lixing
     * @日期 2021/7/4 14:11
     * @Param [key, value, milliseconds 有效期]
     */
    void setKey(String key, E value, long milliseconds);

    /**
     * @描述 尝试添加 key，如果key存在则失败
     * @作者 lixing
     * @日期 2021/7/4 14:11
     * @Param [key, value]
     */
    boolean trySetKey(String key, E value);

    /**
     * @描述 尝试添加 key，如果key存在则失败
     * @作者 lixing
     * @日期 2021/7/4 14:11
     * @Param [key, value, milliseconds 超时时间]
     */
    boolean trySetKey(String key, E value, long milliseconds);

    /**
     * @描述 通过 CAS 更新 key
     * @作者 lixing
     * @日期 2021/7/10 17:40
     * @Param [key, oldValue 更新前的值, newValue 更新后的值]
     * @return boolean
     */
    boolean compareAndSet(String key, E oldValue, E newValue);

    /**
     * @描述 返回 key 的旧值并设置新值
     * @作者 lixing
     * @日期 2021/7/4 14:18
     * @Param [key, newValue 新值]
     * @return E
     */
    E getAndSet(String key, E newValue);

    /**
     * @描述 返回 key 的旧值并设置新值
     * @作者 lixing
     * @日期 2021/7/4 14:18
     * @Param [key, newValue 新值，milliseconds 超时时间]
     * @return E
     */
    E getAndSet(String key, E newValue, long milliseconds);

    /**
     * @描述 查询 key
     * @作者 lixing
     * @日期 2021/7/4 14:18
     * @Param [key]
     * @return E
     */
    E getKey(String key);

    /**
     * @描述 查询 keys
     * @作者 lixing
     * @日期 2021/7/10 17:48
     * @Param [key]
     * @return java.util.List<E>
     */
    Map<String, E> getKeys(String[] keys);

    /**
     * @描述 查询 key 并删除
     * @作者 lixing
     * @日期 2021/7/4 14:18
     * @Param [key]
     * @return E
     */
    E getAndDelete(String key);

    /**
     * @描述 删除key
     * @作者 lixing
     * @日期 2021/7/4 14:05
     * @Param [key]
     * @return boolean
     */
    boolean delKey(String key);

    // TODO ==================================================================================================== 二进制流
    /**
     * @描述 添加
     * @作者 lixing
     * @日期 2021/7/10 13:59
     * @Param [key, bytes, milliseconds 有效期]
     */
    void setBinaryStream(String key, byte[] bytes);
    void setBinaryStream(String key, byte[] bytes, long milliseconds);

    /**
     * @描述 查询
     * @作者 lixing
     * @日期 2021/7/10 14:00
     * @Param [key] 
     * @return org.redisson.api.RBinaryStream
     */
    RBinaryStream getBinaryStream(String key);

    // TODO ======================================================================================================== bit
    /**
     * @描述 添加 bit key
     * @作者 lixing
     * @日期 2021/7/4 14:11
     * @Param [key, index, flag]
     */
    void setBit(String key, long index, boolean flag);

    /**
     * @描述 查询 bit key
     * @作者 lixing
     * @日期 2021/7/4 14:11
     * @Param [key, index]

     */
    boolean getBit(String key, long index);

    /**
     * @描述 获取 bit 数量
     * @作者 lixing
     * @日期 2021/7/4 14:36
     * @Param [key] 
     * @return long
     */
    long getBitSize(String key);

    // TODO ================================================================================================ HyperLogLog
    /**
     * @描述 添加 HyperLogLog
     * @作者 lixing
     * @日期 2021/7/4 14:31
     * @Param [key, value] 

     */
    boolean setHyperLogLog(String key, E value);

    /**
     * @描述 查询 HyperLogLog
     * @作者 lixing
     * @日期 2021/7/4 14:33
     * @Param [key] 
     * @return long
     */
    long getHyperLogLog(String key);

    // TODO =================================================================================================== LIST 列表
    /**
     * @描述 添加 list key
     * @作者 lixing
     * @日期 2021/7/4 14:45
     * @Param [key, value]
     */
    void setList(String key, E value);

    /**
     * @描述 查询 list key
     * @作者 lixing
     * @日期 2021/7/4 14:45
     * @Param [key]
     */
    List<E> getList(String key);

    /**
     * @描述 查询 list key
     * @作者 lixing
     * @日期 2021/7/4 14:45
     * @Param [key, index 索引]
     */
    E getList(String key, int index);

    /**
     * @描述 删除 list key
     * @作者 lixing
     * @日期 2021/7/10 17:59
     * @Param [key, value]
     */
    boolean removeList(String key, E value);

    /**
     * @描述 删除 list key
     * @作者 lixing
     * @日期 2021/7/10 17:59
     * @Param [key, index 索引]
     */
    E removeList(String key, int index);

    // TODO ================================================================================================== Queue 队列
    /**
     * @描述 添加 Queue key
     * @作者 lixing
     * @日期 2021/7/4 15:06
     * @Param [key, value]
     */
    boolean setQueue(String key, E value);

    /**
     * @描述 删除 Queue key 并返回
     * @作者 lixing
     * @日期 2021/7/4 15:06
     * @Param [key, value]
     * @return E
     */
    E getAndDelQueue(String key);

    /**
     * @描述 查询 Queue key
     * @作者 lixing
     * @日期 2021/7/4 15:06
     * @Param [key, value]
     * @return E
     */
    E getQueue(String key);

    // TODO ====================================================================================== BlockingQueue 阻塞队列
    /**
     * @描述 添加 BlockingQueue key
     * @作者 lixing
     * @日期 2021/7/4 15:06
     * @Param [key, value]
     */
    boolean setBlockingQueue(String key, E value);

    /**
     * @描述 删除 BlockingQueue key 并返回
     * @作者 lixing
     * @日期 2021/7/4 15:06
     * @Param [key, milliseconds 超时时间]
     * @return E
     */
    E getAndDelBlockingQueue(String key, long milliseconds);

    /**
     * @描述 查询 BlockingQueue key
     * @作者 lixing
     * @日期 2021/7/4 15:06
     * @Param [key, value]
     * @return E
     */
    E getBlockingQueue(String key);

    // TODO ============================================================================================== Deque 双端队列
    /**
     * @描述 添加 deque(从第一个元素开始添加) key
     * @作者 lixing
     * @日期 2021/7/4 14:54
     * @Param [key, value]
     */
    void setDequeByFirst(String key, E value);

    /**
     * @描述 添加 deque(从最后一个元素开始添加) key
     * @作者 lixing
     * @日期 2021/7/4 14:54
     * @Param [key, value]
     */
    void setDequeByLast(String key, E value);

    /**
     * @描述 获取 deque(从第一个元素开始添加) key
     * @作者 lixing
     * @日期 2021/7/4 15:00
     * @Param [key] 
     * @return E
     */
    E getDequeByFirst(String key);

    /**
     * @描述 获取 deque(从最后一个元素开始添加) key
     * @作者 lixing
     * @日期 2021/7/4 15:00
     * @Param [key]
     * @return E
     */
    E getDequeByLast(String key);

    // TODO =========================================================================================== Deque 阻塞双端队列
    /**
     * @描述 添加 deque(从第一个元素开始添加) key
     * @作者 lixing
     * @日期 2021/7/4 14:54
     * @Param [key, value]
     */
    void setBlockingDequeByFirst(String key, E value);

    /**
     * @描述 添加 deque(从最后一个元素开始添加) key
     * @作者 lixing
     * @日期 2021/7/4 14:54
     * @Param [key, value]
     */
    void setBlockingDequeByLast(String key, E value);

    /**
     * @描述 获取 deque(从第一个元素开始添加) key
     * @作者 lixing
     * @日期 2021/7/4 15:00
     * @Param [key, milliseconds 超时时间]
     * @return E
     */
    E getBlockingDequeByFirst(String key, long milliseconds);

    /**
     * @描述 获取 deque(从最后一个元素开始添加) key
     * @作者 lixing
     * @日期 2021/7/4 15:00
     * @Param [key, milliseconds 超时时间]
     * @return E
     */
    E getBlockingDequeByLast(String key, long milliseconds);

    // TODO ==================================================================================================== SET 集合
    /**
     * @描述 添加 set key
     * @作者 lixing
     * @日期 2021/7/4 15:10
     * @Param [key, value]
     */
    void setSet(String key, E value);

    /**
     * @描述 查询 set key
     * @作者 lixing
     * @日期 2021/7/4 15:13
     * @Param [key] 
     * @return java.util.Set<E>
     */
    Set<E> getSet(String key);

    /**
     * @描述 随机 set key
     * @作者 lixing
     * @日期 2021/7/4 15:15
     * @Param [key, number 随机数量, isDel 是否删除]
     * @return java.util.Set<E>
     */
    Set<E> getSetByRandom(String key, int number, boolean isDel);

    /**
     * @描述 删除 set key
     * @作者 lixing
     * @日期 2021/7/4 15:15
     * @Param [key, value]
     */
    boolean removeSet(String key, E value);

    /**
     * @描述 并集 set key
     * @作者 lixing
     * @日期 2021/7/4 15:19
     * @Param [key1 被并对象1, key2 被并对象2, newKey 如果不为空，则合并和的结果存入该key]
     * @return java.util.Set<E>
     */
    Set<E> getSetUnion(String key1, String key2, String newKey);

    /**
     * @描述 交集 set key
     * @作者 lixing
     * @日期 2021/7/4 15:19
     * @Param [key1 被交对象1, key2 被交对象1, newKey 如果不为空，则合并和的结果存入该key]
     * @return java.util.Set<E>
     */
    Set<E> getSetIntersect(String key1, String key2, String newKey);

    /**
     * @描述 差集 set key
     * @作者 lixing
     * @日期 2021/7/4 15:19
     * @Param [key1 被差对象1, key2 被差对象1, newKey 如果不为空，则合并和的结果存入该key]
     * @return java.util.Set<E>
     */
    Set<E> getSetDifference(String key1, String key2, String newKey);

    // TODO ================================================================================================ ZSET 有序集合
    /**
     * @描述 添加 zset key
     * @作者 lixing
     * @日期 2021/7/4 15:30
     * @Param [key, score, value]
     */
    void setZset(String key, double score, E value);

    /**
     * @描述 修改 zset score
     * @作者 lixing
     * @日期 2021/7/4 15:34
     * @Param [key, value, score]
     */
    void setZsetScore(String key, E value, double score);

    /**
     * @描述 随机 set key
     * @作者 lixing
     * @日期 2021/7/4 15:15
     * @Param [key, number 随机数量]
     * @return java.util.Collection<E>
     */
    Collection<E> getZsetByRandom(String key, int number);

    /**
     * @描述 获取指定score范围内的key数量
     * @作者 lixing
     * @日期 2021/7/4 15:36
     * @Param [key, minxScore 最小得分, minxFlag 是否包含最小得分, maxScore 最高得分, maxFlag 是否包含最大得分]
     * @return long
     */
    long getZsetCount(String key, double minxScore, boolean minxFlag, double maxScore, boolean maxFlag);

    /**
     * @描述 查询 set key 的位置
     * @作者 lixing
     * @日期 2021/7/4 15:15
     * @Param [key, value]
     */
    int rankZset(String key, E value);

    /**
     * @描述 查询 set key 的得分
     * @作者 lixing
     * @日期 2021/7/4 15:15
     * @Param [key, value]
     */
    double scoreZset(String key, E value);

    /**
     * @描述 删除 set key
     * @作者 lixing
     * @日期 2021/7/4 15:15
     * @Param [key, value]
     */
    boolean removeZset(String key, E value);

    /**
     * @描述 查询（升序） zset score
     * @作者 lixing
     * @日期 2021/7/4 15:41
     * @Param [key] 
     * @return java.util.Collection<E>
     */
    Collection<E> getZsetByRange(String key);

    /**
     * @描述 查询（降序） zset score
     * @作者 lixing
     * @日期 2021/7/4 15:41
     * @Param [key]
     * @return java.util.Collection<E>
     */
    Collection<E> getZsetByRangeReversed(String key);

    /**
     * @描述 并集 set key
     * @作者 lixing
     * @日期 2021/7/4 15:19
     * @Param [key1 被并对象1, key2 被并对象1, newKey 如果不为空，则合并和的结果存入该key]
     * @return java.util.Collection<E>
     */
    Collection<E> getZsetUnion(String key1, String key2, String newKey);

    /**
     * @描述 交集 set key
     * @作者 lixing
     * @日期 2021/7/4 15:19
     * @Param [key1 被交对象1, key2 被交对象1, newKey 如果不为空，则合并和的结果存入该key]
     * @return java.util.Collection<E>
     */
    Collection<E> getZsetIntersect(String key1, String key2, String newKey);

    /**
     * @描述 差集 set key
     * @作者 lixing
     * @日期 2021/7/4 15:19
     * @Param [key1 被差对象1, key2 被差对象1, newKey 如果不为空，则合并和的结果存入该key]
     * @return java.util.Collection<E>
     */
    Collection<E> getZsetDifference(String key1, String key2, String newKey);

    // TODO ================================================================================================= 地理空间对象
    /**
     * @描述 添加 geo key
     * @作者 lixing
     * @日期 2021/7/4 15:57
     * @Param [key, geoEntry]

     */
    void setGeo(String key, GeoEntry geoEntry);

    /**
     * @描述 查询 geo 成员
     * @作者 lixing
     * @日期 2021/7/4 15:59
     * @Param [key, memberName] 
     * @return java.util.Map<java.lang.String,org.redisson.api.GeoPosition>
     */
    Map<String, GeoPosition> getGeoMember(String key, String memberName);

    /**
     * @描述 查询 geo 成员之间的执行距离
     * @作者 lixing
     * @日期 2021/7/4 16:00
     * @Param [key, memberName1, memberName2] 
     * @return double
     */
    double getGeoDistance(String key, String memberName1, String memberName2);
}
